Django是一个高级Python Web框架,鼓励快速开发和简洁实用的设计。 Django 学习笔记试图为初学者和高级开发人员提供基本参考,降低新手的入门门槛。
创建一个新工程:
1 |
django-admin.py startproject learning_log . |
创建数据库:
1 |
python manage.py migrate |
运行项目:
1 |
python manage.py runserver |
运行后访问http://localhost:8000/
新建一个app,Django可以建多个app:
1 |
python manage.py startapp learning_logs |
Django模板继承
网页的许多元素在网站的每个页面或网站的某个部分的每个页面上重复出现。 通过为该网站编写一个父模板,为每个部分编写一个父模板,您可以轻松地修改整个网站的外观
父模板
父模板定义一组页面共有的元素,并定义将由各个页面填充的块。
1 2 3 4 5 6 |
<p> <a href="{% url 'learning_logs:index' %}"> Learning Log </a> </p> {% block content %}{% endblock content %} |
子模板
子模板使用{%extended%}模板标签插入父模板的结构。 然后,它为父模板中定义的任何块定义内容。
1 2 3 4 5 6 7 8 |
{% extends 'learning_logs/base.html' %} {% block content %} <p> Learning Log helps you keep track of your learning, for any topic you're learning about. </p> {% endblock content %} |
Django Rest Framework安装:
1 |
$ pip install djangorestframework |
然后,将“ rest_framework”添加到settings.py文件中的INSTALLED_APPS中。
1 2 3 4 |
INSTALLED_APPS = [ # Rest of your installed apps ... 'rest_framework', ] |
使用django shell
1 |
python manage.py shell |
访问数据:
1 2 3 4 5 |
from learning_logs.models import Topic Topic.objects.all() topic = Topic.objects.get(id=1) topic.text 'Chess' |
Django Rest Framework序列化
序列化程序允许将诸如查询集和模型实例之类的复杂数据转换为原生Python数据类型,然后可以轻松地将其呈现为JSON,XML和其他格式。
使用ModelSerializer类:
假设我们想为示例Post模型创建一个PostSerializer,为Comment模型创建CommentSerializer。
1 2 3 4 5 6 7 8 9 10 11 12 |
class PostSerializer(serializers.ModelSerializer): class Meta: model = Post fields = ('id', 'title', 'text', 'created') class CommentSerializer(serializers.ModelSerializer): class Meta: model = Comment fields = ('post', 'user', 'text') |
或者,您也可以使用排除来排除某些字段被序列化。 ModelSerializer具有create()和update()方法的默认实现。
嵌套序列化
默认情况下,实例使用主键序列化以表示关系。 为了获得嵌套序列化,我们可以使用General或Explicit方法。
一般
使用深度参数。
1 2 3 4 5 6 |
class CommentSerializer(serializers.ModelSerializer): class Meta: model = Comment fields = '__all__' depth = 2 |
明确地,您还可以在彼此之间定义和嵌套序列化器…
1 2 3 4 5 6 |
class CommentSerializer(serializers.ModelSerializer): post = PostSerializer() class Meta: model = Comment fields = '__all__' |
因此,在这里,评论的发布字段(我们在models.py中如何命名)将序列化,但是我们在PostSerializer中定义了它。
超链接模型序列化器
这使您的Web API更加易于使用(在浏览器中),并且将是一个不错的功能。
假设我们要查看我们API的每个Post实例中每个帖子的评论。
使用HyperlinkedModelSerializer,我们没有嵌套的主键或嵌套的字段,而是获得了指向每个单独的Comment(URL)的链接。
1 2 3 4 5 6 |
class PostSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Post fields = ('id', 'title', 'text', 'created', 'comments') read_only_fields = ('comments',) |
注意:如果没有read_only_fields,则帖子的创建表单将始终需要输入评论,这是没有意义的(通常在帖子创建后对帖子进行评论)。
超链接的另一种方法是将HyperlinkedRelatedField定义添加到常规序列化程序中。
1 2 3 4 5 6 |
class PostSerializer(serializers.ModelSerializer): comments = serializers.HyperlinkedRelatedField(many=True, view_name='comment-detail', read_only=True) class Meta: model = Post fields = ('id', 'title', 'text', 'created', 'comments') |
动态修改序列化器中的字段
这使得您的Web API更加容易提取有限数量的参数作为响应。 假设您要设置初始化时序列化程序应使用哪些字段。
只需复制以下代码并将其粘贴到您的serliazer文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class DynamicFieldsModelSerializer(serializers.ModelSerializer): def __init__(self, *args, **kwargs): # Don't pass the 'fields' arg up to the superclass fields = kwargs.pop('fields', None) # Instantiate the superclass normally super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs) if fields is not None: # Drop any fields that are not specified in the `fields` argument. allowed = set(fields) existing = set(self.fields.keys()) for field_name in existing - allowed: self.fields.pop(field_name) |
从序列化器类扩展DynamicFieldsModelSerializer
1 2 3 4 |
class UserSerializer(DynamicFieldsModelSerializer): class Meta: model = User fields = ('id', 'username', 'email') |
在字段中提及字段名称
1 |
UserSerializer(user, fields=('id', 'email')) |
在这里,您只会从序列化程序中获得ID和电子邮件,而不是全部。
Django将数据传递
项目中的大多数页面都需要呈现特定于当前用户的数据。
网址参数
URL通常需要接受一个参数,告诉它要从数据库访问哪些数据。 此处显示的第二个URL模式查找特定主题的ID,并将其存储在参数topic_id中。
1 2 3 4 5 |
urlpatterns = [ url(r'^$', views.index, name='index'), url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'), ] |
在视图中使用数据
该视图使用URL中的参数从数据库中提取正确的数据。 在此示例中,视图正在将上下文词典发送到模板,其中包含应在页面上显示的数据。
1 2 3 4 5 6 7 8 9 |
def topic(request, topic_id): """Show a topic and all its entries.""" topic = Topics.objects.get(id=topic_id) entries = topic.entry_set.order_by('-date_added') context = { 'topic': topic, 'entries': entries, } return render(request, 'learning_logs/topic.html', context) |
在模板中使用数据
视图功能的上下文字典中的数据可在模板中使用。 使用模板变量访问该数据,模板变量用双花括号指示。 模板变量后的垂直线表示过滤器。 在这种情况下,称为日期的过滤器会格式化日期对象,并且换行符会在网页上正确呈现段落。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{% extends 'learning_logs/base.html' %} {% block content %} <p>Topic: {{ topic }}</p> <p>Entries:</p> <ul> {% for entry in entries %} <li> <p>{{ entry.date_added|date:'M d, Y H:i' }}</p> <p>{{ entry.text|linebreaks }}</p> </li> {% empty %} <li>There are no entries yet.</li> {% endfor %} </ul> {% endblock content %} |
Django Rest Framework Views
用于为您的Web API创建视图的选项很多,这实际上取决于您想要的内容和个人喜好。
Function-based views:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.parsers import JSONParser from rest_framework import status from posts.models import Post from posts.serializers import PostSerializer @api_view(['GET', 'POST']) def post_list(request, format=None): if request.method == 'GET': posts = Post.objects.all() serializer = PostSerializer(posts, many=True) return Response(serializer.data) elif request.method == 'POST': data = JSONParser().parse(request) serializer = PostSerializer(data=data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
Class-based views:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from rest_framework.response import Response from rest_framework import status from rest_framework.views import APIView from posts.models import Post from posts.serializers import PostSerializer class PostList(APIView): def get(self, request, format=None): snippets = Post.objects.all() serializer = PostSerializer(snippets, many=True) return Response(serializer.data) def post(self, request, format=None): serializer = PostSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
通用类视图:
1 2 3 4 5 6 7 8 |
from rest_framework import generics from posts.models import Post from posts.serializers import PostSerializer class PostList(generics.ListCreateAPIView): queryset = Post.objects.all() serializer_class = PostSerializer |
Using Mixins:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from rest_framework import generics, mixins from posts.models import Post from posts.serializers import PostSerializer class PostList(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin ): queryset = Post.objects.all() serializer_class = PostSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) |
使用ViewSets:
使用ModelViewSet(在这种情况下),您无需创建单独的视图即可获取对象列表和一个对象的详细信息。 ViewSet将以一致的方式为您处理这两种方法。
1 2 3 4 5 6 7 8 9 10 11 |
from rest_framework import viewsets from posts.models import Post from posts.serializers import PostSerializer class PostViewSet(viewsets.ModelViewSet): """ A viewset for viewing and editing post instances. """ queryset = Post.objects.all() serializer_class = PostSerializer |
路由器
ViewSet中的路由器允许使用命名标准自动生成API的URL配置。
1 2 3 4 5 6 |
from rest_framework.routers import DefaultRouter from posts.views import PostViewSet router = DefaultRouter() router.register(r'users', UserViewSet) urlpatterns = router.urls |
ViewSet中的自定义操作
DRF提供了一些帮助程序,可以使用@action装饰器为临时行为添加自定义动作。 路由器将相应地配置其URL。 例如,我们可以在PostViewSet中添加评论操作,以检索特定帖子的所有评论,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
from rest_framework import viewsets from rest_framework.decorators import action from posts.models import Post from posts.serializers import PostSerializer, CommentSerializer class PostViewSet(viewsets.ModelViewSet): ... @action(methods=['get'], detail=True) def comments(self, request, pk=None): try: post = Post.objects.get(id=pk) except Post.DoesNotExist: return Response({"error": "Post not found."}, status=status.HTTP_400_BAD_REQUEST) comments = post.comments.all() return Response(CommentSerializer(comments, many=True)) |
将视图注册为router.register(r’posts’,PostViewSet)后,该操作将在url posts / {pk} / comments /中可用。
Django建立页面
用户可以通过网页与项目进行交互,并且项目的首页可以从没有数据的简单页面开始。 页面通常需要一个URL,一个视图和一个模板。
映射项目的URL
项目的主要urls.py文件告诉Django在哪里可以找到urls.py
与项目中每个应用程序关联的文件。
1 2 3 4 5 6 7 |
from django.conf.urls import include, url from django.contrib import admin urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'', include('learning_logs.urls', namespace='learning_logs')), ] |
映射应用程序的URL
应用程序的urls.py文件告诉Django用于每个URL的视图
该应用程序。 您需要自己制作此文件,并将其保存在
应用程序的文件夹
1 2 3 4 5 6 |
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.index, name='index'), ] |
编写一个简单的视图
视图通常通过模板从请求中获取信息,然后将数据发送到浏览器。 视图功能存储在应用程序的views.py文件中。 这个简单的查看功能不会提取任何数据,但是它使用模板index.html呈现主页。 从django.shortcuts导入渲染
1 2 3 |
def index(request): """The home page for Learning Log.""" return render(request, 'learning_logs/index.html') |
编写一个简单的模板
模板设置页面的结构。 它混合了html和模板代码,就像Python,但功能不一样。 在项目文件夹中创建一个名为模板的文件夹。 在模板文件夹内,创建另一个与应用程序同名的文件夹。 这是应保存模板文件的位置。
1 2 3 4 |
<p>Learning Log</p> <p>Learning Log helps you keep track of your learning, for any topic you're learning about.</p> |
使用Django模型
定义模型
要为您的应用定义模型,请修改在应用文件夹中创建的models.py文件。 str()方法告诉Django如何基于此模型表示数据对象。
1 2 3 4 5 6 7 8 9 10 |
from django.db import models """A topic the user is learning about.""" class Topic(models.Model): text = models.CharField(max_length=200) date_added = models.DateTimeField( auto_now_add=True) def str(self): return self.text |
定义数据模型外键:
1 2 3 4 5 6 7 8 |
class Entry(models.Model): """Learning log entries for a topic.""" topic = models.ForeignKey(Topic) text = models.TextField() date_added = models.DateTimeField( auto_now_add=True) def str(self): return self.text[:50] + "…" |
激活模型
要使用模型,必须将应用添加到元组INSTALLED_APPS中,该元组存储在项目的settings.py文件中
1 2 3 4 5 6 |
INSTALLED_APPS = ( --snip-- 'django.contrib.staticfiles', # My apps 'learning_logs', ) |
迁移数据库
需要修改数据库以存储模型表示的数据类型。
1 2 |
python manage.py makemigrations learning_logs python manage.py migrate |
创建超级账号,超级账号能够访问和管理所有项目:
1 |
python manage.py createsuperuser |
注册模型
您可以在Django的管理网站上注册模型。
使您更轻松地处理项目中的数据。 去做这个,
修改应用的admin.py文件。
1 2 3 |
from django.contrib import admin from learning_logs.models import Topic admin.site.register(Topic) |
安装Django
通常最好将Django安装到虚拟环境中,在该环境中您的项目可以与其他Python项目隔离。 大多数命令都假定您在活动的虚拟环境中工作。
创建一个虚拟环境
1 2 3 |
$ python –m venv v $ source v/bin/activate #激活 $ pip install Django |